import React from 'react'

import Odoo from '../odoo'
import { logError, validateResult, cloneObj, delIndexEle } from '../utility'

export const actions = {
  REFRESH: 'REFRESH',
  LOADMORE: 'LOADMORE'
}

export const statuses = {
  CONNECT_SUCCESS: 'CONNECT_SUCCESS',
  CONNECT_ERROR: 'CONNECT_ERROR',
  CONNECTING: 'CONNECTING',
  SEARCHING_IMAGE: 'SEARCHING_IMAGE',
  SEARCH_IMAGE_SUCCESS: 'SEARCH_IMAGE_SUCCESS',
  SEARCH_IMAGE_ERROR: 'SEARCH_IMAGE_ERROR',
  SEARCHING_TEXT: 'SEARCHING_TEXT',
  SEARCH_TEXT_SUCCESS: 'SEARCH_TEXT_SUCCESS',
  SEARCH_TEXT_ERROR: 'SEARCH_TEXT_ERROR',
  SEARCHING_VIDEO: 'SEARCHING_VIDEO',
  SEARCH_VIDEO_SUCCESS: 'SEARCH_VIDEO_SUCCESS',
  SEARCH_VIDEO_ERROR: 'SEARCH_VIDEO_ERROR',
  GETTING_USER_INFO: 'GETTING_USER_INFO',
  GET_USER_INFO_SUCCESS: 'GET_USER_INFO_SUCCESS',
  GET_USER_INFO_ERROR: 'GET_USER_INFO_ERROR',
  FAVORITING_POST: 'FAVORITING_POST',
  FAVORITE_POST_SUCCESS: 'FAVORITE_POST_SUCCESS',
  FAVORITE_POST_ERROR: 'FAVORITE_POST_ERROR',
  DELING_FAVORITE_POST: 'DELING_FAVORITE_POST',
  DEL_FAVORITE_POST_SUCCESS: 'DEL_FAVORITE_POST_SUCCESS',
  DEL_FAVORITE_POST_ERROR: 'DEL_FAVORITE_POST_ERROR'
}

export const types = {
  ODOO_CONNECT: 'ODOO_CONNECT',
  ODOO_SEARCH_IMAGE: 'ODOO_SEARCH_IMAGE',
  ODOO_SEARCH_TEXT: 'ODOO_SEARCH_TEXT',
  ODOO_SEARCH_VIDEO: 'ODOO_SEARCH_VIDEO',
  GET_USER_INFO: 'GET_USER_INFO',
  FAVORITE_POST: 'FAVORITE_POST',
  DEL_FAVORITE_POST:'DEL_FAVORITE_POST'
  //REFRESH_IMAGES:'REFRESH_IMAGES',
};

const imageFields = [
  'username', 'img_src', 'desc',
  'ctime', 'height', 'width', 'resized_url'
]
const textFields = ['username', 'ctime', 'text']
const videoFields = ['username', 'ctime', 'poster', 'video_src', 'desc']
const favoritePostFields = ['id', 'time', 'user_id']
const favoriteImageFields = [...favoritePostFields, 'image_id']
const favoriteTextFields = [...favoritePostFields, 'text_id']
const favoriteVideoFields = [...favoritePostFields, 'video_id']


const host   = '192.168.31.182'
const port   = 8069
const database = 'spider_backend'
const apiUrl = `http://${host}:${port}/spiderapi`

const initialState = {
  isLogined: false,
  logining: false,
  loginError: false,
  imageDatas:[],
  imageLatestCtime:'',
  imageEarliestCtime:'',
  imageLoading: false,
  textDatas:[],
  textLatestCtime:'',
  textEarliestCtime:'',
  textLoading: false,
  videoDatas:[],
  videoLatestCtime:'',
  videoEarliestCtime:'',
  videoLoading: false,
  loginInfo: null,
  userInfo: {
    favorites: {image:[],text:[],video:[]},
    likes: {image:[],text:[],video:[]},
    favorite_ids:{image:[],text:[],video:[]},
    like_ids:{image:[],text:[],video:[]}
  }
}

/*
post_id - 关联帖子的id，在服务端是外键，在客户端是帖子的详细数据
model   - 关联帖子的类型，在哪个model中查询
time    - 收藏时间
user_id - 收藏的用户id,在服务端查询时使用，不需要返回到客户端
*/

export const actionCreators = {

  // 连接ODDD服务器
  login: (username, password) => async (dispatch, getState) => {
    dispatch({ type: types.ODOO_CONNECT, status: statuses.CONNECTING })
    const config = {
      host,
      port,
      database,
      username,
      password
    }
    const odoo = new Odoo(config)

    try {
      await odoo.connect(config)
      if (odoo && odoo.uid) {
        dispatch({
          type: types.ODOO_CONNECT,
          status: statuses.CONNECT_SUCCESS,
          loginInfo: odoo
        })
        actionCreators.getUserInfo()(dispatch, getState)
      } else {
        const msg = '登录失败，用户名或密码不正确。'
        logError(types.ODOO_CONNECT, '获取uid失败')
        dispatch({
          type: types.ODOO_CONNECT,
          status: statuses.CONNECT_ERROR,
          error: msg
        })
      }
    } catch (e) {
      logError(types.ODOO_CONNECT, e)
      dispatch({
        type: types.ODOO_CONNECT,
        status: statuses.CONNECT_ERROR,
        error: e
      })
    }
  },
  // 获取用户信息 收藏的帖子，点赞的帖子
  getUserInfo: () => async (dispatch, getState) => {
    const { loginInfo, userInfo, textDatas } = getState().odoo
    const newUserInfo = JSON.parse(JSON.stringify(userInfo))
    const params = {
      kwargs: {
        context: loginInfo.context
      },
      model: '',
      method: 'get_favorite_posts',
      args: [[]]
    }

    const models = [
      'spider.favorite.pic', 'spider.favorite.text', 'spider.favorite.video'
    ]

    const tags = ['pic', 'text', 'video']

    try {
      dispatch({
        type: types.GET_USER_INFO,
        status: statuses.GETTING_USER_INFO
      })

      for (let tag of tags) {
        params.model = `spider.favorite.${tag}`
        if (tag === 'pic') {
          tag = 'image'
        }
        const resp = await loginInfo.rpc_call('/web/dataset/call_kw', params)
        const datas = await resp.json()
        validateResult(datas)
        const result = datas.result
        newUserInfo.favorites[tag] = result['favorites']
        newUserInfo.likes[tag] = result['likes']
        newUserInfo.favorite_ids[tag] = result['favorites'].map(
          (rec) => rec[`${tag}_id`]
        )
        newUserInfo.like_ids[tag] = result['likes'].map(
          (rec) => rec[`${tag}_id`]
        )
      }
      let _textDatas = []
      if (newUserInfo.favorites.text.length || newUserInfo.likes.text.length) {
        _textDatas = [...textDatas]
        const favoriteTextSet = new Set(newUserInfo.favorite_ids.text)
        const likeTextSet = new Set(userInfo.like_ids.tetx)
        _textDatas.forEach((post) => {
          post.isFavorited = favoriteTextSet.has(post.id)
          post.isLiked = likeTextSet.has(post.id)
        })
      }
      dispatch({
        type: types.GET_USER_INFO,
        status: statuses.GET_USER_INFO_SUCCESS,
        userInfo: newUserInfo,
        datas: _textDatas
      })
    } catch (e) {
      logError(types.GET_USER_INFO, e)
      dispatch({
        type: types.GET_USER_INFO,
        status: statuses.GET_USER_INFO_ERROR,
        error:e
      })
    }
  },
  // 收藏，点赞帖子
  favoritePost: (data, tag, level) => async (dispatch, getState) => {
    dispatch({
      type: types.FAVORITE_POST,
      status: statuses.FAVORITING_POST,
    })
    const { loginInfo, userInfo, isLogined, textDatas } = getState().odoo
    if (!isLogined) {
      dispatch({
        type: types.FAVORITE_POST,
        status: statuses.FAVORITE_POST_ERROR,
        error: '用户未登陆'
      })
      return
    }
    const newUserInfo = JSON.parse(JSON.stringify(userInfo))
    const model = `spider.favorite.${tag}`

    if (tag === 'pic') {
      tag = 'image'
    }

    const levelKey = `${level}s`
    const levleIdsKey = `${level}_ids`

    try {
      const favoritePost = {
        user_id: loginInfo.uid,
        time: new Date().format("yyyy-MM-dd hh:mm:ss"),
        level
      }
      favoritePost[`${tag}_id`] = data.id

      const resp = await loginInfo.create(model, favoritePost)
      const datas = await resp.json()
      validateResult(datas)
      // 服务端删除成功才可以对客户端数据进行修改
      favoritePost.id = datas.result // result 返回创建的项的id
      favoritePost.post = data // post对应真实数据

      newUserInfo[levelKey][tag].splice(0,0,favoritePost)
      newUserInfo[levleIdsKey][tag].push(data.id)

      let _textDatas = []
      if(tag === 'text') {
        _textDatas = [...textDatas]
        _textDatas.find((post) => {
          if (post.id === data.id) {
            level === 'favorite' ? post.isFavorited = true : post.isLiked = true
            return true
          }
        })
      }

      dispatch({
        type: types.FAVORITE_POST,
        status: statuses.FAVORITE_POST_SUCCESS,
        userInfo: newUserInfo,
        datas: _textDatas
      })
    } catch (e) {
      logError(types.FAVORITE_POST, e)
      dispatch({
        type: types.FAVORITE_POST,
        status: statuses.FAVORITE_POST_ERROR,
        error: e
      })
    }
  },
  // 取消收藏点赞的帖子
  delFavoritePost: (id, tag, level) => async (dispatch, getState) => {
    dispatch({
      type: types.DEL_FAVORITE_POST,
      status: statuses.DELING_FAVORITE_POST
    })
    const { loginInfo, userInfo, isLogined, textDatas } = getState().odoo
    if (!isLogined) {
      dispatch({
        type: types.DEL_FAVORITE_POST,
        status: statuses.DEL_FAVORITE_POST_ERROR,
        error: '用户未登陆'
      })
      return
    }
    // 根据帖子id找到收藏id
    const newUserInfo = JSON.parse(JSON.stringify(userInfo))
    const model = `spider.favorite.${tag}`

    if (tag === 'pic') {
      tag = 'image'
    }

    const levelKey = `${level}s`
    const levleIdsKey = `${level}_ids`
    let favritePostId = null

    const favoritePosts = newUserInfo[levelKey][tag]
    const favoriteIds = newUserInfo[levleIdsKey][tag]
    const index = favoritePosts.findIndex((value, index, arr) => {
      if (value[`${tag}_id`] === id) {
        favritePostId = value.id
        return true
      }
    })

    try {
      const resp = await loginInfo.delete(model, favritePostId)
      const datas = await resp.json()
      if (!datas.result) {
        throw new Error('删除失败')
      }
      // 服务端操作成功才对本地数据进行修改
      newUserInfo[levelKey][tag] = delIndexEle(favoritePosts, index)
      newUserInfo[levleIdsKey][tag] = delIndexEle(favoriteIds, favoriteIds.indexOf(id))

      let _textDatas = []
      if (tag === 'text') {
        _textDatas = [...textDatas]
        _textDatas.find((post) => {
          if (post.id === id) {
            level === 'favorite' ? post.isFavorited = false : post.isLiked = false
            return true
          }
        })
      }

      dispatch({
        type: types.DEL_FAVORITE_POST,
        status: statuses.DEL_FAVORITE_POST_SUCCESS,
        userInfo: newUserInfo,
        datas: _textDatas
      })
    } catch (e) {
      logError(types.DEL_FAVORITE_POST, e)
      dispatch({
        type: types.DEL_FAVORITE_POST,
        status: statuses.DEL_FAVORITE_POST_ERROR,
      })
    }
  },
  // 获取数据 dispatch, getState, modelName, params,
  getDatas: async function ( url, success, error) {
    // const odoo  = getState().odoo
    try {
      // const response = await odoo.odoo.search_read(modelName, params)
      // const rspDatas = await response.json()
      const resp  = await fetch(url)
      const datas = await resp.json()
      const len = datas.length
      const latestCtime = len ? datas[0].ctime : ''
      const earliestCtime = len ? datas[len-1].ctime : ''
      success(datas, latestCtime, earliestCtime)

    } catch (e) {
      error(e)
    }
  },
  // 获取图片
  getImages: (action='') => (dispatch, getState) => {
    let url = `${apiUrl}/new?model=pic`
    const odoo = getState().odoo
    dispatch({
      type: types.ODOO_SEARCH_IMAGE,
      status: statuses.SEARCHING_IMAGE,
    })
    // const modelName = 'spider.pic'
    // let params = {
    //   fields: imageFields,
    //   domain: [],
    //   order: 'ctime desc',
    //   limit: 20
    // }

    if (action === actions.REFRESH && odoo.imageLatestCtime) {
      url = `${apiUrl}/refresh?model=pic&time=${odoo.imageLatestCtime}`
      // params.domain.push(['ctime', '>', odoo.imageLatestCtime])
      // dispatch({type: types.REFRESH_IMAGES, loading:true})
    }
    if (action === actions.LOADMORE && odoo.imageEarliestCtime) {
      url = `${apiUrl}/loadmore?model=pic&time=${odoo.imageEarliestCtime}`
      // 每次加载10条
      // params.limit = 10
      // params.domain.push(['ctime', '<', odoo.imageEarliestCtime])
    }
    const success = (datas, latestCtime, earliestCtime) => {
      if (action === actions.REFRESH &&  datas.length) {
        //dispatch({type: types.REFRESH_IMAGES, loading: false})
        datas = [...datas, ...odoo.imageDatas]
      }
      if (action === actions.LOADMORE && datas.length) {
        datas = [...odoo.imageDatas, ...datas]
      }
      dispatch({
        type: types.ODOO_SEARCH_IMAGE,
        status: statuses.SEARCH_IMAGE_SUCCESS,
        datas,
        latestCtime,
        earliestCtime
      })
    }
    const error = (e) => {
      logError(types.ODOO_SEARCH_IMAGE, e)
      dispatch({
        type: types.ODOO_SEARCH_IMAGE,
        status: statuses.SEARCH_IMAGE_ERROR,
        error:e
      })
    }
    actionCreators.getDatas(url ,success, error)
  },
  // 获取段子
  getTexts: (action='') => (dispatch, getState) => {
    let url = `${apiUrl}/new?model=text`
    const odoo = getState().odoo
    dispatch({
      type: types.ODOO_SEARCH_TEXT,
      status: statuses.SEARCHING_TEXT,
    })
    // const modelName = 'spider.text'
    // let params = {
    //   fields: textFields,
    //   domain: [],
    //   order: 'ctime desc',
    //   limit: 20
    // }

    if (action === actions.REFRESH && odoo.textLatestCtime) {
      url = `${apiUrl}/refresh?model=text&time=${odoo.textLatestCtime}`
      //params.domain.push(['ctime', '>', odoo.textLatestCtime])
      //dispatch({type: types.REFRESH_IMAGES, loading:true})
    }
    if (action === actions.LOADMORE && odoo.textEarliestCtime) {
      url = `${apiUrl}/loadmore?model=text&time=${odoo.textEarliestCtime}`
      // params.domain.push(['ctime', '<', odoo.textEarliestCtime])
    }

    const success = (datas, latestCtime, earliestCtime) => {
      if (action === actions.REFRESH && datas.length) {
        datas = [...datas, ...odoo.textDatas]
      }
      if (action === actions.LOADMORE && datas.length) {
        datas = [...odoo.textDatas, ...datas]
      }
      dispatch({
        type: types.ODOO_SEARCH_TEXT,
        status: statuses.SEARCH_TEXT_SUCCESS,
        datas,
        latestCtime,
        earliestCtime
      })
    }
    const error = (e) => {
      logError(types.ODOO_SEARCH_TEXT, e)
      dispatch({
        type: types.ODOO_SEARCH_TEXT,
        status: statuses.SEARCH_TEXT_ERROR,
        error:e
      })
    }
    actionCreators.getDatas(url, success, error)
  },
  // 获取视频
  getVideos: (action='') => (dispatch, getState) => {
    let url = `${apiUrl}/new?model=video`
    const odoo = getState().odoo
    dispatch({
      type: types.ODOO_SEARCH_VIDEO,
      status: statuses.SEARCHING_VIDEO,
    })
    // const modelName = 'spider.video'
    // let params = {
    //   fields: videoFields,
    //   domain: [],
    //   order: 'ctime desc',
    //   limit: 20
    // }

    if (action === actions.REFRESH && odoo.videoLatestCtime) {
      url = `${apiUrl}/refresh?model=video&time=${odoo.videoLatestCtime}`
      // params.domain.push(['ctime', '>', odoo.videoLatestCtime])
      //dispatch({type: types.REFRESH_IMAGES, loading:true})
    }
    if (action === actions.LOADMORE && odoo.videoEarliestCtime) {
      url = `${apiUrl}/loadmore?model=video&time=${odoo.videoEarliestCtime}`
      // params.domain.push(['ctime', '<', odoo.videoEarliestCtime])
    }

    const success = (datas, latestCtime, earliestCtime) => {
      if (action === actions.REFRESH && datas.length) {
        datas = [...datas, ...odoo.videoDatas]
      }
      if (action === actions.LOADMORE && datas.length) {
        // 返回的数据不为空则在原数据尾部添加数据
        datas = [...odoo.videoDatas, ...datas]
      }
      dispatch({
        type: types.ODOO_SEARCH_VIDEO,
        status: statuses.SEARCH_VIDEO_SUCCESS,
        datas,
        latestCtime,
        earliestCtime
      })
    }
    const error = (e) => {
      logError(types.ODOO_SEARCH_VIDEO, e)
      dispatch({
        type: types.ODOO_SEARCH_VIDEO,
        status: statuses.SEARCH_VIDEO_ERROR,
        error:e
      })
    }
    actionCreators.getDatas(url, success, error)
  },
}

export const reducer = (state = initialState, action) => {
  const {
    type, status, loginInfo, error, loading, latestCtime, earliestCtime, datas,
    userInfo, model, favoritePost
  } = action;
  switch (type) {
    case types.ODOO_CONNECT: {
      if (status === statuses.CONNECTING) {
        // 连接odoo服务器时也需要一个loading状态
        return {
          ...state, status,
          logining: true,
          isLogined: false,
          loginError: false
        }
      }
      if (status === statuses.CONNECT_SUCCESS) {
        return {
          ...state, loginInfo, status,
          logining: false,
          isLogined: true,
          loginError: false }
      }
      if (status === statuses.CONNECT_ERROR) {
        return {
          ...state, status, error,
          logining: false,
          isLogined: false,
          loginError: true
        }
      }
    }
    case types.ODOO_SEARCH_IMAGE: {
      if(status === statuses.SEARCHING_IMAGE) {
        return { ...state, status, imageLoading: true }
      }
      if( status === statuses.SEARCH_IMAGE_SUCCESS ) {
        let newState = {
          ...state,
          status,
          imageLoading: false
        }
        if (datas.length) {
          Object.assign(newState,
            {
              imageDatas: datas,
              imageLatestCtime: latestCtime,
              imageEarliestCtime: earliestCtime
            })
        }
        return newState
      }
      if ( status === statuses.SEARCH_IMAGE_ERROR ) {
        return { ...state, status, error, imageLoading: false }
      }
    }
    case types.ODOO_SEARCH_VIDEO: {
      if( status === statuses.SEARCHING_VIDEO ) {
        return {...state, status, videoLoading: true}
      }
      if( status === statuses.SEARCH_VIDEO_SUCCESS ) {
        let newState = {
          ...state,
          status,
          videoLoading: false
        }
        if (datas.length) {
          Object.assign(newState,
            {
              videoDatas: datas,
              videoLatestCtime: latestCtime,
              videoEarliestCtime: earliestCtime
            })
        }
        return newState
      }

      if ( status === statuses.SEARCH_VIDEO_ERROR ) {
        return { ...state, status, error, videoLoading: false }
      }
    }
    case types.ODOO_SEARCH_TEXT: {
      if( status === statuses.SEARCHING_TEXT ) {
        return {...state, status, textLoading: true}
      }
      if( status === statuses.SEARCH_TEXT_SUCCESS ) {
        let newState = {
          ...state,
          status,
          textLoading: false
        }
        if (datas.length) {
          Object.assign(newState,
            {
              textDatas: datas,
              textLatestCtime: latestCtime,
              textEarliestCtime: earliestCtime
            })
        }
        return newState
      }
      if ( status === statuses.SEARCH_TEXT_ERROR ) {
        return { ...state, status, error, textLoading: false }
      }
    }
    // case types.REFRESH_IMAGES: {
    //   return {...state, imageLoading:loading}
    // }
    case types.GET_USER_INFO: {
      if ( status === statuses.GETTING_USER_INFO ){
        // { ...state, userInfo, status }
        // GETTING_USER_INFO时并未返回userInfo，因此userInfo为undefined
        return { ...state, status }
      }
      if ( status === statuses.GET_USER_INFO_SUCCESS ){
        const newState = { ...state, userInfo, status}
        if (datas.length) {
          Object.assign(newState, {textDatas: datas})
        }
        return newState
      }
      if ( status === statuses.GET_USER_INFO_ERROR ){
        return { ...state, status, error }
      }
    }
    case types.FAVORITE_POST: {
      if (status === statuses.FAVORITING_POST) {
        return {...state, status, textLoading: true}
      }
      if ( status === statuses.FAVORITE_POST_SUCCESS ) {
        const newState = { ...state, userInfo, status}
        if (datas.length) {
          Object.assign(newState, {textDatas: datas})
        }
        return newState
      }
      if (status === statuses.FAVORITE_POST_ERROR) {
        return {...state, status, error, textLoading: false}
      }
    }
    case types.DEL_FAVORITE_POST: {
      if (status === statuses.DELING_FAVORITE_POST) {
        return {...state, status}
      }
      if (status === statuses.DEL_FAVORITE_POST_SUCCESS) {
        const newState = { ...state, userInfo, status}
        if (datas.length) {
          Object.assign(newState, {textDatas: datas})
        }
        return newState
      }
      if (status === statuses.DEL_FAVORITE_POST_ERROR) {
        return {...state, status}
      }
    }
    default: {
      return state
    }
  }
};
